/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package yoga.algo.polygon;

import java.awt.Polygon;
import yoga.algo.coding.ICoding;
import yoga.algo.coding.IGenotypeCodec;
import yoga.algo.coding.binary.BinaryString;
import yoga.algo.coding.binary.BinaryStringCoding;

/**
 *
 * @author Yogev Montekyo
 */
public class PolygonBinaryGentypeCodec implements IGenotypeCodec<Polygon>
{
    @Override
    public Polygon decode(ICoding<Polygon> coding) throws IllegalArgumentException
    {

        BinaryStringCoding<Polygon> binaryStringPolygonCoding;
        if (!(coding instanceof BinaryStringCoding))
        {
            throw new IllegalArgumentException("Type missmatch, cannot cross " + this.getClass().getName() + " with supplied coding reference");
        }

        binaryStringPolygonCoding = (BinaryStringCoding<Polygon>) coding;

        int numberOfCoordinates = binaryStringPolygonCoding.getNumberOfArguments();
        int coordinateBitSize = binaryStringPolygonCoding.getSizeOfArgument();
        BinaryString binaryString = binaryStringPolygonCoding.getBinaryString();

        Polygon polygon = new Polygon();

        for (int argumentIndex = 0; argumentIndex < numberOfCoordinates; argumentIndex++)
        {
            int x = 0;
            int counter = 0;
            for (int bitIndex = coordinateBitSize / 2 - 1; bitIndex >= 0; bitIndex--)
            {
                int binaryIndex = argumentIndex * coordinateBitSize + bitIndex;
                boolean currentBit = binaryString.getBit(binaryIndex);
                if (currentBit)
                {
                    x += Math.pow(2, counter);
                }
                counter++;

            }
            int y = 0;
            counter = 0;
            for (int bitIndex = coordinateBitSize - 1; bitIndex >= coordinateBitSize / 2 + 1; bitIndex--)
            {
                int binaryIndex = argumentIndex * coordinateBitSize + bitIndex;
                boolean currentBit = binaryString.getBit(binaryIndex);
                if (currentBit)
                {
                    y += Math.pow(2, counter);
                }
                counter++;
            }

            polygon.addPoint(x, y);
        }

        return polygon;
    }

    @Override
    public BinaryStringCoding<Polygon> encode(Polygon type) throws IllegalArgumentException
    {
        int singleDimSize = 9;
        int coordinateSize = singleDimSize * 2;
        int numberOfCoordinates = type.npoints;
        BinaryString binaryString = new BinaryString(numberOfCoordinates * coordinateSize);

        for (int argumentIndex = 0; argumentIndex < type.npoints; argumentIndex++)
        {
            int x = type.xpoints[argumentIndex];
            int y = type.ypoints[argumentIndex];

            String strX = Integer.toBinaryString(x);
            String strY = Integer.toBinaryString(y);


            int startIndex = argumentIndex * coordinateSize + singleDimSize - 1;
            int endIndex = startIndex - singleDimSize + 1;
            int stringSize = strX.length() - 1;

            for (int index = startIndex; (index > endIndex) && (stringSize >= 0); index--)
            {
                if (strX.charAt(stringSize) == '1')
                {
                    binaryString.setBit(index, true);
                }
                else
                {
                    binaryString.setBit(index, false);
                }
                stringSize--;
            }

            startIndex += singleDimSize;
            endIndex += singleDimSize;
            stringSize = strY.length() - 1;

            for (int index = startIndex; (index > endIndex) && (stringSize >= 0); index--)
            {
                if (strY.charAt(stringSize) == '1')
                {
                    binaryString.setBit(index, true);
                }
                else
                {
                    binaryString.setBit(index, false);
                }
                stringSize--;
            }
        }

        BinaryStringCoding<Polygon> polygonBinaryStringCoding = new BinaryStringCoding<Polygon>(binaryString);
        polygonBinaryStringCoding.setNumberOfArguments(numberOfCoordinates);
        polygonBinaryStringCoding.setSizeOfArgument(coordinateSize);

        return polygonBinaryStringCoding;
    }
}
